﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using Fuse8.ContentManagementFramework.BizFacade.Services.Contents;
using Fuse8.ContentManagementFramework.BizFacade.Services.Contents.Queryable;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.BizFacade.Services;
using Fuse8.ContentManagementFramework.Administration.Models;
using Fuse8.ContentManagementFramework.SystemFacade;
using Fuse8.ContentManagementFramework.Domain.Special;
using Fuse8.ContentManagementFramework.Web.MvcPowered;

namespace Fuse8.ContentManagementFramework.Administration.Controllers
{
    [ValidateInput(false)]
    public class CmsContentController : CmsAdminController<CmsContent>
    {
        private CmsContentTypeService _contentTypeService;
        private CmsContentService _contentService;

        protected virtual CmsContentTypeService ContentTypeService
        {
            get
            {
                if (_contentTypeService == null)
                {
                    _contentTypeService = new CmsContentTypeService();
                }

                return _contentTypeService;
            }
        }

        protected virtual CmsContentService ContentService
        {
            get
            {
                if (_contentService == null)
                {
                    _contentService = new CmsContentService();
                }

                return _contentService;
            }
        }

        public virtual ActionResult Index(int id, int? page, bool isInAjax = false)
        {
            ActionResult result = null;

            if (id > 0)
            {
                var contentType = ContentTypeService.FindOne(id);
                if (contentType != null)
                {
                    result = PartialView("Index",
                        new CmsAdminContentModel
                        {
                            Contents = GenericContentService.GetAll(id).OrderBy(p=>p["PublicContentId"]).Skip((page.GetValueOrDefault(1)-1)*DefaultPageSize).Take(DefaultPageSize),
                            Total = GenericContentService.GetAll(id).Count(),
                            ContentType = contentType,
                            HidePager = isInAjax
                        });
                }
            }

            return result ?? RedirectToAction("index", "cmscontenttype");
        }

        public virtual ActionResult Add(int id)
        {
            ViewBag.ContentTypeName = ContentTypeService.FindOne(id).ContentTypeName;
            return View(id);
        }

        [HttpPost]
        public virtual ActionResult Add(CmsContentModel model)
        {
            ActionResult result = null;

            if (ModelState.IsValid)
            {
                var content = model.ToDomainEntity();
                content.Id = 0;                          
                ContentService.Add(content);

                SaveMetas(model, content);
            }

            return result ?? RedirectToAction("edit", "cmscontenttype", new { id = model.ContentTypeId });
        }

        private static void SaveMetas(CmsContentModel model, CmsContent content)
        {
            if (model.Metas != null)
            {
                foreach (var meta in model.Metas)
                {
                    content.SetMetaValue(meta.Name, meta.Value, Type.GetType(meta.Type), true);
                }
            }
        }

        public virtual ActionResult Edit(int id)
        {
            var model = new CmsContentModel(id, 0);
            ViewBag.ContentTypeName = ContentTypeService.FindOne(model.ContentTypeId).ContentTypeName;
            return View(model);
        }

        public virtual ActionResult Preview(int id)
        {
            var model = new CmsContentModel(id, 0) {EditMode = EditMode.Revision};
            return View("Edit", model);
        }

        [HttpPost]
        public virtual ActionResult Edit(CmsContentModel model)
        {
            ActionResult result;
            if (ModelState.IsValid)
            {
                var content = model.ToDomainEntity();
                
                ContentService.Save(content);

                SaveMetas(model, content);
                result = RedirectToAction("edit", "cmscontenttype", new { id = model.ContentTypeId });
            }
            else
            {
                var contentType = ContentTypeService.FindOne(model.ContentTypeId);
                ViewBag.ContentTypeName = contentType.ContentTypeName;
                model.ContentType = contentType;
                result = View(model);
            }

            return result;
        }

        public virtual ActionResult ContentDetails(int id, int contentTypeId, EditMode mode = EditMode.Usual)
        {
            return PartialView(new CmsContentModel(id, contentTypeId){EditMode = mode});
        }

        public virtual ActionResult ContentPicker(string defaultContentType, dynamic additionalParameters)
        {
            var types = ContentTypeService.FindAll().Where(p => !p.IsSystemType).OrderBy(p => p.ContentTypeName);
            IEnumerable<SelectListItem> items = null;
            string id = "";
            if (!string.IsNullOrEmpty(defaultContentType))
            {
                var type =
                    types.FirstOrDefault(
                        p => p.ContentTypeName.Equals(defaultContentType, StringComparison.OrdinalIgnoreCase));
                if (type != null)
                {
                    id = type.Id.ToString();
                    items =
                        GenericContentService.GetAll(type.Id).OrderBy(p => p["ContentTitle"]).ToList().Select(
                            p => new SelectListItem() {Text = p["ContentTitle"].ToString(), Value = p.Id.ToString()});
                }                
            }
            return PartialView("ContentPicker", new {Types = types.ToList(), Items = items, DefaultId = id}.ToExpando());
        }

        public ActionResult GetItems(int id)
        {
            return Json(GenericContentService.GetAll(id).OrderBy(p => p["ContentTitle"]));
        }

        public override ActionResult Delete(int id)
        {
            var content = ContentService.FindOne(id);
            ContentService.Remove(id);
            return Index(content.ContentTypeId, null);
        }

        public ActionResult Revisions(int publicId, int typeId)
        {
            var items = GenericContentService.GetAllRevisions(typeId)
                                             .Where(p => p.PropertyEquals("PublicContentId", publicId))
                                             .JoinWith<CmsUser>(p => p.Id, "LastUpdatedBy", p => new{p.Firstname, p.Lastname})                                             
                                             .OrderByDescending(p => p["Id"])
                                             .SelectProperties("Id", "ContentTitle", "DateLastUpdated", "LastUpdatedBy");

            return PartialView(items.ToList());
        }
    }
}
